package com.tfswx.jkgl.core.service.impl;

import com.github.pagehelper.page.PageMethod;
import com.tfswx.jkgl.core.bean.Csdy;
import com.tfswx.jkgl.core.bean.JkglRuntimeData;
import com.tfswx.jkgl.core.bean.SjmxXtMxdy;
import com.tfswx.jkgl.core.bean.TSjmxXtMxstgx;
import com.tfswx.jkgl.core.dao.SqlMapper;
import com.tfswx.jkgl.core.dto.ClcxInputDTO;
import com.tfswx.jkgl.core.dto.CsdygxInputDTO;
import com.tfswx.jkgl.core.dto.DeleteInputDTO;
import com.tfswx.jkgl.core.dto.SaveInputDTO;
import com.tfswx.jkgl.core.dto.SelectInputDTO;
import com.tfswx.jkgl.core.interfaces.delete.AbstractDeleteHandleComponent;
import com.tfswx.jkgl.core.interfaces.delete.impl.SjmxDeleteHandleComponent;
import com.tfswx.jkgl.core.service.SjczService;
import com.tfswx.jkgl.core.sjcc.DataSave;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 数据操作服务
 *
 * @author Smile
 * @date 2021/12/7
 */
@Slf4j
@Service
public class SjczServiceImpl implements SjczService {
    @Resource
    private DataSave dataSave;

    @Resource
    private JkglRuntimeData jkglRuntimeData;

    @Resource
    private SjmxDeleteHandleComponent sjmxDeleteHandleComponent;

    @Override
    public Object save(SaveInputDTO dto) {
        if ("sql".equals(dto.getClcx().getClcxlx())) {
            String sql = dto.getClcx().getClcxcs();
            // sql = CommonUtil.replace(sql, ((Map<String, Object>) dto.getCsdy()));
            try (SqlMapper sqlMapper = new SqlMapper()) {
                sqlMapper.execute(sql, dto.getCsdy());
            }
        } else {
            return dataSave.save(dto);
        }
        return true;
    }

    @Override
    public Object select(SelectInputDTO dto) {
        ClcxInputDTO clcx = dto.getClcx();
        if (Objects.isNull(clcx) || StringUtils.isEmpty(clcx.getClcxlx())) {
            throw new RuntimeException("数据处理类型不能为空");
        }
        Csdy ccpz = dto.getCcpz();
        if (ccpz == null) {
            throw new RuntimeException("出参配置不能为空");
        }
        Object param = dto.getCsdy();
        if ("sql".equals(clcx.getClcxlx())) {
            String sql = clcx.getClcxcs();
            return queryData(sql, param, ccpz);
        } else {
            String mxbm = clcx.getClcxcs();
            // 3、依据模型编码获取模型定义信息
            SjmxXtMxdy mx = jkglRuntimeData.getMxdyList().get(mxbm);
            if (Objects.isNull(mx)) {
                throw new RuntimeException("传入参数数据模型编码错误：" + mxbm);
            }
            // 4、依据模型编码获模型实体表关系信息
            List<TSjmxXtMxstgx> allMxstgx = jkglRuntimeData.getMxstgxList().get(mxbm);

            StringBuilder sql = new StringBuilder();

            List<String> columInfoList = getColumInfoList(ccpz);
            if (columInfoList.isEmpty()) {
                throw new RuntimeException("出参配置不能为空");
            }
            String columInfo = String.join(",", columInfoList);
            sql.append("SELECT ").append(columInfo).append(" FROM ").append(mx.getZSTMC());

            if (allMxstgx != null) {
                List<TSjmxXtMxstgx> collect = allMxstgx.stream()
                        .filter(item -> StringUtils.isNotEmpty(item.getGLGXLX()))
                        .filter(item -> "N".equalsIgnoreCase(item.getSFSC()))
                        .collect(Collectors.toList());
                List<String> sql1 = this.createSql(collect, mx.getZSTMC());
                sql.append("\n").append(String.join("\n", sql1));
            }
            List<CsdygxInputDTO> csgx = dto.getCsgx();
            sql.append(" WHERE ").append(mx.getZSTMC()).append(".SFSC='N'");
            Map<String, Object> temp = (Map<String, Object>) param;
            for (CsdygxInputDTO csdygxInputDTO : csgx) {
                String stmc = csdygxInputDTO.getStmc();
                String zdmc = csdygxInputDTO.getZdmc();
                String csbm = csdygxInputDTO.getCsbm();
                if (StringUtils.isBlank(stmc) || StringUtils.isBlank(zdmc) || StringUtils.isBlank(csbm)) {
                    continue;
                }
                Object o = temp.get(csbm);
                if (o == null || "".equals(o.toString())) {
                    continue;
                }

                sql.append(" AND ").append(stmc).append(".").append(zdmc).append("=#{").append(csbm).append("}");
            }

            return queryData(sql.toString(), param, ccpz);
        }
    }

    private Object queryData(String sql, Object param, Csdy ccpz) {
        try (SqlMapper sqlMapper = new SqlMapper()) {
            Csdy.PageData fydx = ccpz.getFydx();
            if (fydx != null) {
                // 分页
                return PageMethod.startPage(fydx).doSelectPageInfo(() -> {
                    sqlMapper.selectList(sql, param, ccpz);
                });
            } else if ("Map".equalsIgnoreCase(ccpz.getCslx())) {
                return sqlMapper.selectOne(sql, param, ccpz);
            }
            return sqlMapper.selectList(sql, param, ccpz);
        }
    }

    private List<String> createSql(List<TSjmxXtMxstgx> collect, String tableName) {
        List<String> outerJoinInfoList = new ArrayList<>();
        List<TSjmxXtMxstgx> collect1 = collect.stream()
                .filter(item -> tableName.equals(item.getZSTMC()))
                .collect(Collectors.toList());
        for (TSjmxXtMxstgx item : collect1) {
            outerJoinInfoList.add("LEFT JOIN " + item.getCSTMC() + " ON " + item.getGLGXSQL() + " AND " + item.getCSTMC() + ".SFSC='N'");
            List<String> sql = createSql(collect, item.getCSTMC());
            outerJoinInfoList.addAll(sql);
        }

        return outerJoinInfoList;
    }

    private List<String> getColumInfoList(Csdy ccpz) {
        List<String> objects = new ArrayList<>();
        if (!StringUtils.isEmpty(ccpz.getZdmc())) {
            String selectColumnInfo = ccpz.getStmc() + "." + ccpz.getZdmc() + " AS " + ccpz.getCsbm();
            objects.add(selectColumnInfo);
        }
        List<Csdy> csdy = ccpz.getCsdy();
        if (csdy != null && !csdy.isEmpty()) {
            for (Csdy csdy1 : csdy) {
                if (csdy1 != null) {
                    objects.addAll(getColumInfoList(csdy1));
                }
            }
        }
        return objects;
    }

    /**
     * 删除数据
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delete(final DeleteInputDTO dto) throws Exception {
        ClcxInputDTO clcx = dto.getClcx();
        if (clcx == null) {
            throw new Exception("数据处理类型不能为空");
        }
        String clcxlx = clcx.getClcxlx();
        if (StringUtils.isBlank(clcxlx)) {
            throw new Exception("数据处理类型不能为空");
        }
        Object param = dto.getCsdy();
        List<Map<String, Object>> maps = new ArrayList<>();
        if (param instanceof Map) {
            maps.add((Map<String, Object>) param);
        } else if (param instanceof List) {
            maps.addAll((List<Map<String, Object>>) param);
        }

        if ("sql".equals(clcxlx)) {
            String sql = clcx.getClcxcs();
            if (StringUtils.isBlank(sql)) {
                throw new IllegalArgumentException("处理程序模式为sql但是缺少sql语句");
            }
            try (SqlMapper sqlMapper = new SqlMapper()) {
                for (Map<String, Object> map : maps) {
                    sqlMapper.execute(sql, map);
                }
            }
            return true;
        } else {
            String mxbm = clcx.getClcxcs();
            if (StringUtils.isBlank(mxbm)) {
                throw new RuntimeException("模型编码不能为空");
            }
            SjmxXtMxdy mx = jkglRuntimeData.getMxdyList().get(mxbm);
            if (mx == null) {
                throw new RuntimeException("传入参数数据模型编码错误：" + dto.getClcx().getClcxcs());
            }
            List<String> tables = new ArrayList<>();
            tables.add(mx.getZSTMC());
            List<TSjmxXtMxstgx> allMxstgx = jkglRuntimeData.getMxstgxList().get(mxbm);
            if (allMxstgx != null) {
                List<String> zstmcs = allMxstgx.stream().filter(item -> "N".equalsIgnoreCase(item.getSFSC()))
                        .map(TSjmxXtMxstgx::getZSTMC).filter(StringUtils::isNoneBlank)
                        .distinct()
                        .collect(Collectors.toList());
                tables.addAll(zstmcs);

                List<String> cstmc = allMxstgx.stream().filter(item -> "N".equalsIgnoreCase(item.getSFSC()))
                        .map(TSjmxXtMxstgx::getCSTMC).filter(StringUtils::isNoneBlank)
                        .distinct()
                        .collect(Collectors.toList());
                tables.addAll(cstmc);
            }
            tables = tables.stream().distinct().collect(Collectors.toList());
            for (Map<String, Object> map : maps) {
                // 5、遍历需要删除(逻辑删除)数据的表信息以及表关联信息，封装删除语句
                // for (final String deleteTable : dto.getScbjh()) {
                //
                //     if (!tables.contains(deleteTable)) {
                //         continue;
                //     }
                //
                //     SQL deleteSql = new SQL();
                //     deleteSql.UPDATE(deleteTable);
                //     deleteSql.SET("SFSC  = 'Y'");
                //     // 遍历分组后的表数据，生成指定表的删除语句
                //     Iterator<CsdygxInputDTO> iterator = dto.getCsgx().iterator();
                //     while (iterator.hasNext()) {
                //         CsdygxInputDTO next = iterator.next();
                //         if (next.getStmc().equals(deleteTable)) {
                //             //字段名称为空则跳过
                //             if(ObjectUtil.isNull(next.getZdmc())){
                //                 continue;
                //             }
                //             String value = String.valueOf(jsonObject.get(next.getCsbm()));
                //             if (!StringUtils.isEmpty(value)) {
                //                 deleteSql.WHERE(next.getZdmc() + " = '" + value + "'");
                //             }
                //         }
                //     }
                //
                //     if (!deleteSql.toString().contains("where") && !deleteSql.toString().contains("WHERE")) {
                //         throw new Exception("需要删除的表" + deleteTable + "没有删除条件");
                //     }
                //
                //     deleteSqlList.add(deleteSql.toString());
                // }
            }
        }
        AbstractDeleteHandleComponent deleteHandleComponent = sjmxDeleteHandleComponent;

        List<String> deleteSqlLists = deleteHandleComponent.createSql(dto);
        if (deleteSqlLists.isEmpty()) {
            return false;
        }

        try (SqlMapper sqlMapper = new SqlMapper()) {
            for (final String deleteSqlList : deleteSqlLists) {
                sqlMapper.execute(deleteSqlList, null);
            }
        }

        // 执行单条删除语句
        return true;
    }
}
